import functools

from opentelemetry import trace
from werkzeug.wrappers import Response as ResponseBase

from myapp.const.error import CommonErrorCode, ErrorCode

# Initializes a tracer for OpenTelemetry to enable distributed tracing.
tracer = trace.get_tracer(__name__)


def wrap_response(func):
    """A decorator to wrap API responses, ensuring a consistent format.

    This decorator automatically formats the return value of a function
    into a dictionary with 'result', 'status', and 'message' keys,
    unless the return value is already a Werkzeug Response object.
    It also integrates with OpenTelemetry for tracing.
    """
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        # 函数名称
        # Get the name of the wrapped function for tracing purposes.
        func_name = func.__name__
        # Start a new span for the response wrapping operation.
        with tracer.start_as_current_span(f'wrap_response.{func_name}'):
            # Execute the original function and get its data.
            data = func(*args, **kwargs)
            # If the data is already a Werkzeug Response, return it directly.
            if isinstance(data, ResponseBase):
                return data

            # Otherwise, wrap the data in a standardized response dictionary.
            ret = {'result': data, 'status': 0, 'message': 'success'}
            return ret

    return wrapper


class BizError(Exception):
    """Custom exception class for business logic errors.

    This exception allows for specific error codes, messages, and optional
    data to be associated with business-related failures.
    """
    def __init__(self, code=1, message=None, data=None):
        # If the provided code is an instance of ErrorCode enum, use its value.
        if isinstance(code, ErrorCode):
            code = code.value
            # If it's an internal error and no specific message is provided, set a default message.
            if code == CommonErrorCode.INTERNAL_ERROR.value and message is None:
                message = '系统异常，请联系技术支持或提交反馈信息'

        # Initialize the error with a code, message, and result data.
        self.code = code
        self.message = message
        self.result = data